package br.perfiman.model;

import java.util.Comparator;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

/**
 *
 * @author Wagner Costa
 * @since 27/12/2007
 * @version 1.0
 *
 */
@Entity
//@XStreamAlias("Trade")
public class Trade implements AbstractEntity{
	private static final long serialVersionUID = 2524271468682243904L;

	public static final Integer TYPE_BUY = 1;
	public static final Integer TYPE_SELL = 2;
	
	public static final Integer OPERATION_TYPE_COMMON = 1;
	public static final Integer OPERATION_TYPE_DAYTRADE = 2;
	public static final Integer OPERATION_TYPE_MIX = 3;

	@Id
	@GeneratedValue
    protected Long id;

	@ManyToOne(optional=false)
	protected Asset asset;

	@Column(nullable=false)
    protected Integer quantity;

	@Column(nullable=false)
    protected Integer type;

	@Column(nullable=false)
    protected Date date;

	@Column(nullable=false)
    protected Double price;
	
	@Column(name="buy_average_price")
    protected Double buyAveragePrice;
	
	@Column(nullable=true)
    protected Double profit;

	@Column(nullable=false)
    protected Double brokerage;

	@Column(nullable=false)
    protected Double fees;
	
	//Internal Revenue Service
	@Column(nullable=false)
    protected Double irs;

    @Column(length=500, nullable=false)
    protected String comments;

    @Column(name="operation_type", nullable=false)
    protected Integer operationType;
    
    @ManyToOne(optional=false)
	protected Broker broker;
    
    @ManyToOne(optional=true)
	protected Trade parent;

	/**
	 * @return the asset
	 */
	public Asset getAsset() {
		return asset;
	}

	/**
	 * @return the brokerage
	 */
	public Double getBrokerage() {
		return brokerage;
	}

	/**
	 * @return the date
	 */
	public Date getDate() {
		return date;
	}

	/**
	 * @return the fees
	 */
	public Double getFees() {
		return fees;
	}

	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @return the comments
	 */
	public String getComments() {
		return comments;
	}

	/**
	 * @return the quantity
	 */
	public Integer getQuantity() {
		return quantity;
	}

	/**
	 * @return the type
	 */
	public Integer getType() {
		return type;
	}

	/**
	 * @return the price
	 */
	public Double getPrice() {
		return price;
	}

	/**
	 * @param asset the asset to set
	 */
	public void setAsset(Asset asset) {
		this.asset = asset;
	}

	/**
	 * @param brokerage the brokerage to set
	 */
	public void setBrokerage(Double brokerage) {
		this.brokerage = brokerage;
	}

	/**
	 * @param date the date to set
	 */
	public void setDate(Date date) {
		this.date = date;
	}

	/**
	 * @param fees the fees to set
	 */
	public void setFees(Double fees) {
		this.fees = fees;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @param comments the comments to set
	 */
	public void setComments(String comments) {
		this.comments = comments;
	}

	/**
	 * @param quantity the quantity to set
	 */
	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(Integer type) {
		this.type = type;
	}

	/**
	 * @param price the price to set
	 */
	public void setPrice(Double price) {
		this.price = price;
	}

	/**
	 * @return the dayTrade
	 */
	public Integer getOperationType() {
		return operationType;
	}
	
	public boolean isDayTradeOperation(){
		return (getOperationType() == null || !getOperationType().equals(OPERATION_TYPE_COMMON))? true: false;
	}

	/**
	 * @param dayTrade the dayTrade to set
	 */
	public void setOperationType(Integer dayTrade) {
		this.operationType = dayTrade;
	}

	public Object getEntityId() {
		return getId();
	}

	@Override
	public String toString() {
		StringBuilder b = new StringBuilder();
		b.append("id: ").append(getId());
		b.append("; [Asset: ").append(getAsset());
		b.append("]; quantity: ").append(getQuantity());
		b.append("; type: ").append(getType());
		b.append("; date: ").append(getDate());
		b.append("; price: ").append(getPrice());
		b.append("; BuyAveragePrice: ").append(getBuyAveragePrice());
		b.append("; brokerage: ").append(getBrokerage());
		b.append("; fees: ").append(getFees());
		b.append("; Profit: ").append(getProfit());
		b.append("; comments: ").append(getComments());
		b.append("; operationType: ").append(getOperationType());
		b.append("; irs: ").append(getIrs());
		b.append("; Parent: ").append(getParent());
		return b.toString();
	}

	public Double getIrs() {
		return irs;
	}

	public void setIrs(Double irs) {
		this.irs = irs;
	}

	public Double getBuyAveragePrice() {
		return buyAveragePrice;
	}

	public Double getProfit() {
		return profit;
	}

	public void setBuyAveragePrice(Double buyAveragePrice) {
		this.buyAveragePrice = buyAveragePrice;
	}

	public void setProfit(Double profit) {
		this.profit = profit;
	}
	
	public class TradeComparator implements Comparator<Trade>{
		public int compare(Trade o1, Trade o2) {
			return o1.getQuantity() - o2.getQuantity();
		}
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		Trade trade = new Trade();
		trade.setAsset(getAsset());
		trade.setBrokerage(getBrokerage());
		trade.setBuyAveragePrice(getBuyAveragePrice());
		trade.setComments(getComments());
		trade.setDate(getDate());
		trade.setFees(getFees());
		trade.setIrs(getIrs());
		trade.setOperationType(getOperationType());
		trade.setPrice(getPrice());
		trade.setProfit(getProfit());
		trade.setQuantity(getQuantity());
		trade.setType(getType());
		trade.setBroker(getBroker());
		return trade;
	}

	public Trade getParent() {
		return parent;
	}

	public void setParent(Trade parent) {
		this.parent = parent;
	}

	public Broker getBroker() {
		return broker;
	}

	public void setBroker(Broker broker) {
		this.broker = broker;
	}
}
